<script lang='ts' setup>
import {  computed, onUnmounted, reactive, ref, watch } from 'vue'
import type { TooltipProps, TooltipEmits,TooltipInstance  } from './type'
import { createPopper, type Instance } from '@popperjs/core';
import useClickOutside from '../../hooks/useClickOutside';
import { debounce } from 'lodash-es'
const props = withDefaults(defineProps<TooltipProps>(), {
  placement: 'bottom',
  trigger: 'hover',
  transition:'fade',
  openDelay: 0,
  closeDelay: 0,
})
const emits = defineEmits<TooltipEmits>()
const isOpen = ref(false)
const popperNode = ref<HTMLElement>()
const triggerNode = ref<HTMLElement>()
const popperContainerNode = ref<HTMLElement>()
const poppperOptions = computed(()=>{
  return {
    placement: props.placement,
    modifiers: [
      {
        name: 'offset',
        options: {
          offset: [0, 9],
        },
      }
    ],
    ...props.popperOptions
  }
})
let events: Record<string, Function> = reactive({})
let outerEvents: Record<string, Function> = reactive({})
let popperInstance: null | Instance = null

const togglePopper = () => {
  if (isOpen.value) {
    closeFinal()
  } else {
    openFinal()
  }
}

const open = () => {
  isOpen.value = true
  emits('visible-change', true)

}
const close = () => {
  isOpen.value = false
  emits('visible-change', false)
}

// 延迟显示和隐藏
const openDebounce = debounce(open, props.openDelay)
const closeDebounce = debounce(close, props.closeDelay)

// 防抖显示和隐藏
const openFinal = () => {
  closeDebounce.cancel()
  openDebounce()
}
const closeFinal = () => {
  openDebounce.cancel()
  closeDebounce()
}

const attachEvents = () => {
  if (props.trigger === 'hover') {
    events['mouseenter'] = openFinal
    outerEvents['mouseleave'] = closeFinal
  } else if (props.trigger === 'click') {
    events['click'] = togglePopper
  }
}


// 点击外部关闭tooltip弹框
useClickOutside(popperContainerNode, () => {
  if (props.trigger === 'click' && isOpen.value && !props.manual) {
    closeFinal()
  }

})

watch(() => props.trigger, (newValue,oldValue) => {
    if (newValue !== oldValue) {
        events = {}
        outerEvents = {}
        attachEvents()
    }
})

watch(() => props.manual, (isManual) => {
    // 手动模式下，不监听事件
    if (isManual) {
        events = {}
        outerEvents = {}
    } else{
        // 非手动模式下，监听事件
        attachEvents()
    }
})


watch(isOpen, (newValue) => {
  if (newValue) {
    if (triggerNode.value && popperNode.value) {
      popperInstance = createPopper(triggerNode.value, popperNode.value, poppperOptions.value)
    } else {
      popperInstance?.destroy()
    }
  }
}, { flush: 'post'})


function init() {
    if (!props.manual) {
        attachEvents()
    }
}
init()

onUnmounted(()=>{
    // 销毁
  popperInstance?.destroy()
})

defineExpose<TooltipInstance>({
  show: openFinal,
  hide: closeFinal,

})
</script>
<template>
<div class="vk-tooltip" v-on="outerEvents" ref="popperContainerNode">
    <div v-on="events" class="vk-tooltip__trigger" ref="triggerNode">
        <slot></slot>
    </div>
    <Transition :name="transition">
      <div v-if="isOpen" class="vk-tooltip__popper" ref="popperNode">
          <slot name='content'>
              {{ content }}
          </slot>
          <div id="arrow" data-popper-arrow></div>
      </div>
    </Transition>
</div>
</template>